#pragma once

#include "noncopyable.h"
#include "InetAddress.h"
#include "Callbacks.h"
#include "Buffer.h"
#include "Timestamp.h"

#include <memory>
#include <string>
#include <atomic>

class Channel;
class EventLoop;
class Socket;


// TcpConnection 保存了连接相关的数据，但是 Poller 里监听的还是 Channel
// TcpConnection 里的一部分数据，包括 sockfd ，打包成 Channel 扔给 Poller
// Poller 监听到 Channel 上有事件发生，就调用回调函数
// 这些回调函数是 Channel 从 TcpConnection 里拿过来的
// 用户自定义回调函数 → TcpServer → TcpConnection → Channel

/**
 * TCP连接类，用于客户端和服务器
 * TcpServer 通过 Acceptor 有一个新用户连接，通过 accept 函数拿到 connfd
 * → TcpConnection 设置回调 → Channel → Poller → Channel 的回调操作 handleEventWithGuard
*/
class TcpConnection : noncopyable , public std::enable_shared_from_this<TcpConnection>
{
// public std::enable_shared_from_this<TcpConnection> -- 得到当前对象的智能指针
public:
    // 使用已连接的sockfd构造TcpConnection，用户不应创建此对象
    TcpConnection(EventLoop* loop, const std::string& name, int sockfd, const InetAddress& localAddr, const InetAddress& peerAddr);
    ~TcpConnection();

    EventLoop* getLoop() const { return loop_; }
    const std::string name() const { return name_; }
    const InetAddress& localAddress() const { return localAddr_; }
    const InetAddress& peerAddress() const { return peerAddr_; }

    bool connected() const { return state_ == kConnected; }  // 是否处于已连接状态

    // 发送数据
    void send(const std::string& buf);
    // 关闭连接
    void shutdown();

    // 设置一系列回调，TcpServer调用设置TcpConnection，TcpServer::newConnection()调用这些方法设置回调函数
    void setConnectionCallback(const ConnectionCallback& cb)  // 设置新连接回调
    { connectionCallback_ = cb; }
    void setMessageCallback(const MessageCallback& cb)  // 设置有读写消息时的回调
    { messageCallback_ = cb; }
    void setWriteCompleteCallback(const WriteCompleteCallback& cb)  // 设置消息发送完成后的回调
    { writeCompleteCallback_ = cb; }
    void setHighWaterMarkCallbck(const HighWaterMarkCallback& cb)  // 设置高水位回调
    { highWaterMarkCallback_ = cb; }
    void setCloseCallback(const CloseCallback& cb){ closeCallback_ = cb; }

    // 连接建立，当TcpServer接受新连接时调用，只应调用一次
    void connectEstablished();
    // 连接销毁，当TcpServer将此TcpConnection从映射map中删除时调用，只应调用一次
    void connectDestroyed();

private:
    enum StateE  // 表示连接状态的枚举
    {
        kDisconnected,  // 已断开
        kConnecting,  // 正在连接
        kConnected,  // 已连接
        kDisconnecting  // 正在断开
    };

    EventLoop* loop_;  // 这里绝对不是baseloop_，因为TcpConnection都是在subloop里面管理的，除非没有setThreadNum创建工作线程
    const std::string name_;
    std::atomic_int state_;  // 状态
    bool reading_;

    // 这里和Acceptor类似，Acceptor在mainLoop里，TcpConnection在TcpServer里
    std::unique_ptr<Socket> socket_;
    std::unique_ptr<Channel> channel_;

    const InetAddress localAddr_;  // 当前主机IpPort
    const InetAddress peerAddr_;  // 对端（客户端）IpPort

    // 用户自定义回调函数 → TcpServer → TcpConnection → Channel
    ConnectionCallback connectionCallback_;  // 有新连接时的回调
    MessageCallback messageCallback_;  // 有读写消息时的回调
    WriteCompleteCallback writeCompleteCallback_;  // 消息发送完成后的回调
    HighWaterMarkCallback highWaterMarkCallback_;  // 高水位回调
    CloseCallback closeCallback_;  // 关闭连接回调
    size_t highWaterMark_;  // 水位线标志
    
    Buffer inputBuffer_;  // 读缓冲，接收数据的缓冲区
    Buffer outputBuffer_;  // 写缓冲，发送数据的缓冲区 send 

    // Poller 通知 Channel 的时候调用的回调
    void handleRead(Timestamp receiveTime);
    void handleWrite();
    void handleClose();
    void handleError();

    void sendInLoop(const void* message, size_t len);
    void shutdownInLoop();

    void setState(StateE state) { state_ = state; }
};